<?php
/**
 *  💡 免责声明：本软件不得用于商业用途，仅做学习交流
 *  ⚠️ 权利声明：本软件由版权人提供产品技术支持
 *  📅 项目编号：NX2025-0135
 */

namespace App\Service\User;

use App\Models\DividendAccount;
use App\Models\GroupOrderBatche;
use App\Models\PointAccount;
use App\Models\PointSetting;
use App\Models\PointTransaction;
use App\Models\User;
use App\Service\BaseService;
use App\Service\Notifications\NotificationService;
use App\Service\Pools\DividendService;
use Illuminate\Support\Facades\DB;
use Throwable;

class PointAccountServices extends BaseService
{
    public function isItSufficient($user_id, $amount): bool
    {
        $pointAccount = PointAccount::query()->where('user_id', $user_id)->first();
        $withdraw_point = bcsub($pointAccount->available_points, $pointAccount->frozen_points, 6);
        if ($withdraw_point < $amount) {
            return false;
        }
        return true;
    }

    /**
     * 积分池自动分红.
     */
    public function pointAutoDividends()
    {
        [$point_price, $bean_price] = $this->getTheDividendAmount();

        if (PointSetting::query()->value('on_point') == 1) {
            //积分分红
            if ($point_price == 0) {
                return;
            }
            $this->dividend($point_price, 1);
        }
    }

    /**
     * 获取分红金额. 昨日分红池/总购买商品销售额.
     */
    protected function getTheDividendAmount()
    {
        return DividendService::make()->Conversion();
    }

    /**
     * @param $reward
     * @param $dividendAmount
     * @param $dividendAccount
     * @param mixed $type
     * @throws Throwable
     */
    public function dividend($dividendAmount, $type): void
    {
        $reward = RewardAccountService::make();
        $dividendAccount = DividendAccountServices::make();
        $amount_name = 'point_amount';
        if ($type == 2) {
            $amount_name = 'bean_amount';
        }
        //TODO 价值等于 昨日分红池/总分红账户   分红账户 * 价值  发放到个人
        DividendAccount::query()
            ->where($amount_name, '>', 0)
            ->chunkById(200, function ($lists) use ($reward, $dividendAmount, $dividendAccount, $type) {
                $lists->each(function ($list) use ($reward, $dividendAmount, $dividendAccount, $type) {
                    if ($type == 1) {
                        $amount = bcmul($dividendAmount, $list->point_amount, 2);
                        if ($list->point_amount < $amount) {
                            $amount = $list->point_amount;
                        }
                    } else {
                        $amount = bcmul($dividendAmount, $list->bean_amount, 2);
                        if ($list->bean_amount < $amount) {
                            $amount = $list->bean_amount;
                        }
                    }

                    DB::transaction(function () use ($amount, $list, $reward, $dividendAccount, $type) {
                        if ($type == 1) {
                            $msg = sprintf('分红池积分奖励:%s', $amount);
                        } else {
                            $msg = sprintf('分红池通证奖励:%s', $amount);
                        }
                        $reward->recharge($list->user_id, $amount, 1, $msg);
                        $dividendAccount->consumption($list->user_id, $amount, $type);
                    });
                });
            });
    }

    /**
     * 添加积分.
     * @param $user_id
     * @param $amount
     * @param mixed $describe
     * @param mixed $type
     * @return false
     */
    public function recharge($user_id, $amount, $describe = '充值', $type = 1): bool
    {
        if ($amount < 0) {
            return false;
        }
        $pointAccount = PointAccount::query()->where('user_id', $user_id)->first();
        $withdraw_point = bcsub($pointAccount->available_points, $pointAccount->frozen_points, 6);
        $pointAccount->withdraw_points = bcadd($withdraw_point, $amount, 6);
        $pointAccount->total_point = bcadd($pointAccount->total_point, $amount, 6);
        $pointAccount->available_points = bcadd($pointAccount->available_points, $amount, 6);
        $pointAccount->save();
        $this->transactionHistory($user_id, $amount, $pointAccount->available_points, $type, $describe, 1);
        return true;
    }

    /**
     * 添加积分获取日志.
     * @param $user_id
     * @param $amount
     * @param $balance
     * @param $transaction_type
     * @param $type
     * @param mixed $describe
     * @param mixed $change_type
     */
    private function transactionHistory($user_id, $amount, $balance, $transaction_type, $describe, $change_type)
    {
        PointTransaction::query()->Create([
            'user_id' => $user_id,
            'amount' => $amount,
            'balance' => $balance,
            'transaction_type' => $transaction_type,
            'describe' => $describe,
            'status' => 2,
            'change_type' => $change_type,
        ]);
        $user = User::query()->find($user_id);
        if (filled($user)) {
            NotificationService::make()->SystemNotify($user, $describe);
        }
    }

    /**
     * @param $user_id
     * @param $amount
     * @param mixed $describe
     * @param mixed $type
     * @return false|\Illuminate\Database\Eloquent\HigherOrderBuilderProxy|mixed|string
     */
    public function consumption($user_id, $amount, $describe = '消费', $type = 2)
    {
        $pointAccount = PointAccount::query()->where('user_id', $user_id)->first();
        $withdraw_point = bcsub($pointAccount->available_points, $pointAccount->frozen_points, 6);
        if ($withdraw_point < $amount) {
            $user = User::query()->find($user_id);
            NotificationService::make()->SystemNotify($user, $describe.'积分不足,操作失败');
            return false;
        }
        $pointAccount->withdraw_points = bcsub($withdraw_point, $amount, 6);
        $pointAccount->available_points = bcsub($pointAccount->available_points, $amount, 6);
        $pointAccount->save();
        $this->transactionHistory($user_id, $amount, $pointAccount->available_points, $type, $describe, 2);
        return $pointAccount->withdraw_points;
    }

    public function DynamicDividendDistribution() //动态分红
    {
        if (PointSetting::query()->value('on_point') == 1) {
            $reward = RewardAccountService::make();
            $subDividendPool = DividendService::make()->getSubDividendPool();
            $ss = SinglePoolService::make();
            if ($subDividendPool->point_released_amount > 0 && $subDividendPool->total_number > 0) {
                $amount = bcdiv($subDividendPool->point_released_amount, $subDividendPool->total_number, 2);
                GroupOrderBatche::query()
                    ->where('type', 2)
                    ->where('status', 1)
                    ->where('is_dividend', 0)
                    ->where('group_date', now()->subDay()->toDateString())
                    ->chunkById(500, function ($orders) use ($reward, $amount,$ss) {
                        $orders->each(function ($order) use ($reward, $amount,$ss) {
                            $res2 = $ss->consumption($order->user_id,$amount,sprintf('团购分红:%s', $amount));
                            if ($res2){
                                $res = $this->consumption($order->user_id, $amount,sprintf('团购分红积分转换:%s', $amount), 3);
                                if ($res) {
                                    $reward->recharge($order->user_id, $amount, 1, sprintf('团购分红:%s', $amount));
                                    $order->increment('is_dividend');
                                } else {
                                    $reward->consumption($order->user_id, 0, 1, '积分不足 团购分红失败');
                                }
                            }
                        });
                    });
            }

        }
    }

//    是否足够

    /**
     * 通证池自动分红.
     */
    public function beanAutoDividends()
    {
        [$point_price, $bean_price] = $this->getTheDividendAmount();
        if (PointSetting::query()->value('on_bean') == 1) {
            //通证分红
            if ($bean_price == 0) {
                return;
            }
            $this->dividend($bean_price, 2);
        }
    }
}
